import { GLAPI, PROXY } from './GLAPI.service';
import { File } from 'ionic-native';
import { Platform } from 'ionic-angular';
import { Http, Response } from '@angular/http';
import { Injectable } from '@angular/core';
import { GLBookContent } from './GLBookContent';
import { GLFolderLike } from './GLFolderLike';
import { GLFolder } from './GLFolder';
import { Observable } from 'rxjs';
import 'rxjs/Rx';

let API_URI = PROXY ? "/api" : "http://tech.lds.org/glweb";

@Injectable()
export class GLAPI_glweb2_JSON extends GLAPI {

  constructor(private http: Http, platform: Platform) {
    super(platform);
  }

  getCatalogInfo() {
    return this.getAPIResource("catalog.json", "catalog.query", {
      platformid: 10,
      languageid: 1
    }).then((content) => {
      return JSON.parse(content).catalog;
    });
  }

  getFile(filepath: string, json: boolean = false, url: string) {
    filepath = "api2/" + filepath;
    if (PROXY) {
      url = url.replace("http://broadcast3.lds.org", "/broadcast3");
    }
    return this.checkFile(filepath).then((found: boolean): PromiseLike<string> => {
      console.log("Found? " + found)
      if (found) {
        console.log("Reading " + filepath);
        console.log(this.fs);
        return File.readAsText(this.fs, filepath)
          .then((content: string) => {
            if (json) {
              // If it's not valid, this should throw an error and redownload
              JSON.parse(content);
            }
            return content;
          }).catch((err) => {
            console.error(err);
            return this.download(url, filepath);
          })
      }
      else {
        return this.download(url, filepath);
      }
    });
  }

  getAPIResource(filepath: string, action: string, params?) {
    params = params || {};
    params.action = action;
    params.platformid = 10;
    params.languageid = 1;
    return this.getFile(filepath, true, API_URI + this.query(params));
  }

  private checkFile(filepath: string) {
    return this.ready().then(() => {
      return File.checkFile(this.fs, filepath).catch(this.codeOne);
    });
  }

  private codeOne(err) {
    // Sometimes it throws NOT_FOUND_ERRs?
    if (err.code === 1) {
      return false;
    }
    throw err;
  }

  private getBookPath(id: string) {
    return "books" + id + ".json";
  }

  isBookAvailable(id: string) {
    return this.checkFile(this.getBookPath(id));
  }

  getBook(id: string, url: string, parentFolder: GLFolderLike) {
    return this.getFile(this.getBookPath(id), true, url).then((content) => {
      console.log("got book")
      return new GLBookContent(JSON.parse(content), parentFolder);
    })
  }

  loadCatalog() {
    return this.getCatalogInfo().then((info) => new GLFolder(info, this));
  }

  private download(url, filepath) {
    let res: Observable<Response> = this.http.get(url);
    return res.map((value: Response) => {
      console.log("got value");
      return value.text();
    }).toPromise().then((content: string) => {
      console.log("got content");
      console.log(this.fs);
      console.log(filepath);
      return this.mkdirp(filepath).then(() => {
        console.log("we made it here");
        return File.createFile(this.fs, filepath, true);
      }).then(() => {
        console.log("created file");
        return File.writeFile(this.fs, filepath, content, {
          replace: true
        })
          .then(() => {
            console.log("wrote to file");
            return content;
          });
      }).catch((err) => {
        console.log("Something's wrong here");
        console.error(err);
      });
    });
  }

  private mkdirp(filepath: string) {
    let ind = filepath.lastIndexOf("/");
    if (ind < 0) {
      return Promise.resolve();
    }
    let newPath = filepath.substr(0, ind);
    console.log(newPath);
    return File.checkDir(this.fs, newPath).catch(this.codeOne).then((found: boolean) => {
      if (found) {
        console.log("already here");
        return Promise.resolve();
      }
      return this.mkdirp(newPath).then(() => File.createDir(this.fs, newPath, true)).then(() => {
        console.log("created " + newPath);
      }, (err) => {
        console.log("creating dir failed");
        console.error(err);
      });
    });
  }
}